Array.prototype.sort = function(reverse) {
	reverse = reverse?true:false;
	var tmp;
	for(var i=0; i<this.length-1; i++) {
		for(var j=i+1; j<this.length; j++) {
			var condition = reverse ? this[i]<this[j] : this[i]>this[j];
			if(condition) {
				tmp = this[i];
				this[i] = this[j];
				this[j] = tmp;
			}
		}
	}
	
	return this;
}
Array.prototype.sum = function() {
	var ret = 0;
	for(var i=0; i<this.length; i++) {
		ret += this[i];
	}
	return ret;
}
Array.prototype.sum2 = function(num) {
	var tmp = Array();
	ret = 0;
	for(var i=0; i<this.length; i++) {
		val = parseInt(this[i]); val = val>0 ? val : 0;
		tmp[val] = typeof(tmp[val])=="undefined" ? 0 : tmp[val];
		tmp[val] = tmp[val]+1;
	}
	
	if(parseInt(num)>0) {
		var it = 0;
		for(x in tmp) {
			if(tmp[x]>=num && x>it) {
				it = x;
			}
		}
		ret = it*num;
	}else{
		ret = tmp;
	}
	return ret;
}
Array.prototype.implode = function(glue) {
	var ret = "";
	for(var i=0; i<this.length; i++) {
		if(i>0) {
			ret += glue;
		}
		ret += this[i];
	}
	return ret;
}

/**********************************************************/

Yamb = function(expr) {
	
	this.txt = [];
	this.txt["straight"] = "K";
	this.txt["trilling"] = "T";
	this.txt["full"] = "F";
	this.txt["poker"] = "P";
	this.txt["yamb"] = "Y";
	
	this.games = ["down", "free", "up", "call", "hand"];
	this.countdown = 13 * this.games.length;
	
	this.container = $(expr);
	this.table = $('<table class="yamb" />');
	this.container.append(this.table);
	this.btnThrow = $('<input type="button" value="T H R O W" class="throw-button" />');
	
	this.throwCount = 3;
	this.locked = true;
	this.called = false;
	this.rolling = [0,0,0,0,0,0];
	this.isHand = false;
	this.interval;
	
	this.init();
}

Yamb.prototype.init = function() {
	var _Y = this;
	this.btnThrow.click(function() {
		_Y.locked = false;
		_Y.undo("hide");
		if(_Y.throwCount>0) {
			var _BTN = $(this);
			_BTN.attr("disabled","disabled");
			
			var dicesSelected = _Y.container.find("ul.dices li[locked=1]").length;
			if(_Y.throwCount>2 || dicesSelected==0) {
				_Y.isHand = true;
			}else{
				_Y.isHand = false;
			}
			
			_Y.locked = true;
			_Y.rolling = [1,1,1,1,1,1];
			_Y.rollDice(0);
			_Y.interval = setInterval(function(){
				if(!_Y.isRolling()) {
					clearInterval(_Y.interval);
					_BTN.attr("disabled",false);
					_Y.interval = null;					
					_Y.throwCount--;
					_Y.locked = false;
					_Y.container.find(".display").html(3-_Y.throwCount);
				}
			}, 100);
		}
	});
}
Yamb.prototype.isRolling = function() {
	var ret = false;
	for(var i=0; i<this.rolling.length; i++) {
		if(this.rolling[i]) {
			ret = true;
			break;
		}
	}
	return ret;
}
Yamb.prototype.rollDice = function(index) {
	index = index>0?index:0;
	dice = this.container.find("ul.dices li").eq(index);
	locked = parseInt(dice.attr("locked")); locked = locked>0 ? true : false;
	if(!locked) {
		var spins = Math.floor(Math.random()*5) + 1;
		this._rollDice(index,dice,spins,0);
	}else{
		this.rolling[index] = 0;
	}
	if(index<5) {
		this.rollDice(index+1);
	}
}
Yamb.prototype._rollDice = function(index, dice, spins, spin) {
	var _Y = this;
	if(spin<spins) {
		tmp = Math.floor(Math.random()*6) + 1;
		dice.attr("class","");
		dice.addClass("dice-"+(i+1));
		dice.addClass("value"+tmp);
		dice.attr("value",tmp);
		setTimeout(function(){
			_Y._rollDice(index, dice, spins, spin+1);
		}, 200);
	}else{
		_Y.rolling[index] = 0;
	}
}

Yamb.prototype.make = function() {
	var _Y = this;
	
	var dismask = $('<div class="disable-mask" />');
	_Y.container.prepend(dismask);
	
	_Y.table.mousedown(function(){return false})
	
	// header
	tr = $('<tr class="head" />');
	tr.append('<td class="empty" />');
	for(i=0; i<this.games.length; i++) {
		tr.append('<td><img src="'+root+'/img/gui/column_'+this.games[i]+'.png" alt="'+this.games[i]+'" /></td>')
	}
	tr.append('<td class="empty" />');
	this.table.append(tr);
	
	// 1-6 rows
	for(i=0; i<6; i++) {
		this.makeRow((i+1));
	}
	// sum
	this.makeRow("sum",true);
	
	// max/min
	this.makeRow("max");
	this.makeRow("min");
	// sum
	this.makeRow("sum",true);
	
	this.makeRow("straight");
	this.makeRow("trilling");
	this.makeRow("full");
	this.makeRow("poker");
	this.makeRow("yamb");

	//sum
	this.makeRow("sum",true);
	
	//total
	tr = $('<tr class="sum" />');
	for(i=0; i<(this.games.length+1); i++) {
		tr.append('<td class="empty" />');
	}
	tr.append('<td class="total yamb-total" />');
	this.table.append(tr);
	
	//dices
	var dices = $('<ul class="dices" />');
	for(i=1; i<7; i++) {
		li = $('<li class="dice-'+i+'" value="0" />');
		li.click(function(){
			if(_Y.throwCount<3 && !_Y.isRolling()) {
				var numLocked = $(this).parent().find("li[locked=1]").length;
				if($(this).attr("value")) {
					locked = parseInt($(this).attr("locked")); locked = locked>0 ? 1 : 0;
					locked = numLocked<5 ? locked : 1;
					$(this).attr("locked",locked ? 0 : 1);
				}
			}
		});
		dices.append(li);
	}
	this.table.after(dices);
	
	// display
	var display = $('<div class="display">0</div>');
	dices.after(display);
	display.after(this.btnThrow);
	
	// countdown
	this.container.append('<div class="yamb-countdown" value="'+this.countdown+'">'+this.countdown+'</div>');
	
	// game result
	var html = '<div class="result">';
	html += 'Game Over';
	html += '<h1 class="points">0</h1>';
	html += '<a href="javascript:void(0)" onclick="location.reload();">play again</a>';
	html += '</div>';
	var resultinfo = $(html);
	this.container.before(resultinfo);
	
	this.container.append('<br clear="all" />');
}

Yamb.prototype.makeRow = function(label, sum) {
	var _Y = this;
	sum = sum ? true : false;
	label = label+""
	
	
	var txtLabel = sum ? "&#8721;" : (_Y.txt[label.toLowerCase()] ? _Y.txt[label.toLowerCase()] : label.toUpperCase());
	
	tr = $('<tr game="'+label+'" class="'+(sum?"sum":"")+'" />');
	tr.append('<td class="label">'+txtLabel+'</td>');
	for(j=0; j<this.games.length; j++) {
		td = $('<td game="'+(this.games[j])+'" class="'+(sum?"":"field")+'" />');
		if(!sum) {
			td.click(function(){
				_Y.setValue($(this));
			});
		}
		tr.append(td);
	}
	tr.append('<td class="'+(sum?"total":"empty")+'" />');
	this.table.append(tr);
}

Yamb.prototype.setValue = function(td) {
	var _Y = this;
	var column_game = td.attr("game").toLowerCase();
	var row_game = td.parent().attr("game").toLowerCase();
	
	if(!td.attr("value") && !_Y.locked) {
		var dices = this.getDicesValues();
		
		var tr = td.parent();
		var prev = tr.prev();
		if(prev.hasClass("sum")) {
			prev = prev.prev();
		}
		var prev_td = prev.find("td[game="+column_game+"]");
		var next = tr.next();
		if(next.hasClass("sum")) {
			next = next.next();
		}
		var next_td = next.find("td[game="+column_game+"]");
		
		var td_position = td.position();
		$("ul.dices li[locked=1]").each(function(index){
			var dice = $(this);
			var clone = dice.clone();
			var dice_position = dice.position();
			clone.css({
				position:"absolute",
				left: dice_position.left,
				top: dice_position.top
			});
			dice.after(clone);
			clone.animate({
				width: td.width(),
				height: td.height(),
				left: td_position.left,
				top: td_position.top,
				opacity: 0.2
			},500,null, function(){
				clone.remove();
			});
		});
		
		switch(column_game) {
			case "down":
				if((prev_td.hasClass("field") && typeof(prev_td.attr("value")) != "undefined") || prev.hasClass("head")) {
					_Y._setValue(td,column_game,row_game,dices);
				}
				break;
			case "free":
				_Y._setValue(td,column_game,row_game,dices);
				break;
			case "up":
				if((next_td.hasClass("field") && typeof(next_td.attr("value")) != "undefined") || tr.attr("game")=="yamb") {
					_Y._setValue(td,column_game,row_game,dices);
				}
				break;
			case "call":
				if(_Y.throwCount>1){
					var called = parseInt(td.attr("called"));
					this.table.find("td[game=call]").attr("called",0);
					td.attr("called",called>0?0:1);
					_Y.called = !_Y.called;
					switch(row_game) {
						case "1":
						case "2":
						case "3":
						case "4":
						case "5":
						case "6":
							var val = this.gameValueNUM(dices, row_game);
							if(val == 5*parseInt(row_game)) {
								td.attr("called",0);
								_Y.called = false;
								_Y._setValue(td,column_game,row_game,dices);
							}
							break;
						case "straight":
							var val = this.gameValueSTRAIGHT(dices);
							if(val>0) {
								td.attr("called",0);
								_Y.called = false;
								_Y._setValue(td,column_game,row_game,dices);
							}
							break;
					}
				}else{
					if(parseInt(td.attr("called"))>0) {
						td.attr("called",0);
						_Y.called = false;
						_Y._setValue(td,column_game,row_game,dices);
					}
				}
				break;
			case "hand":
				if(_Y.isHand) {
					_Y._setValue(td,column_game,row_game,dices);
				}else{
					_Y._setValue(td,column_game,row_game,[0,0,0,0,0]);
				}
				break;
			default:
				alert(column_game);
		}
		_Y.calculateSums();
	}
}
Yamb.prototype._setValue = function(td, column_game, row_game, dices) {
	var fieldUpdated = false;
	switch(row_game) {
		case "1":
		case "2":
		case "3":
		case "4":
		case "5":
		case "6":
			sum = this.gameValueNUM(dices, row_game);
			fieldUpdated = this._setValueTD(td,sum);
			break;
		
		case "max":
		case "min":
			if(dices.length<5) {
				if(row_game.match(/^max$|^min$/)) {
					var called = parseInt(td.attr("called"));
					called = called>0?0:1;
					this.called = called ? true : false;
					td.attr("called",called);
				}
				alert("You have to select 5 dices.");
				return;
			}
			sum = dices.sum();
			fieldUpdated = this._setValueTD(td,sum);
			break;
			
		case "straight":
			val = this.gameValueSTRAIGHT(dices);
			fieldUpdated = this._setValueTD(td,val);
			break;
			
		case "trilling":
			sum = dices.sum2(3);
			sum = sum>0 ? sum+20 : 0;
			fieldUpdated = this._setValueTD(td,sum);
			break;
		case "full":
			sum = dices.sum2();
			it_3 = 0;
			it_2 = 0;
			for(x in sum) {
				if(sum[x]>=3) {
					it_3 = x;
					sum[x] -= 3
				}
			}
			for(x in sum) {
				if(sum[x]==2) {
					it_2 = x;
				}
			}
			if(it_2>0 && it_3>0) {
				sum = 30 + 3*it_3 + 2*it_2;
			}else{
				sum = 0;
			}
			fieldUpdated = this._setValueTD(td,sum);
			break;
		case "poker":
			sum = dices.sum2(4);
			sum = sum>0 ? sum+40 : 0;
			fieldUpdated = this._setValueTD(td,sum);
			break;
		case "yamb":
			sum = dices.sum2(5);
			sum = sum>0 ? sum+50 : 0;
			fieldUpdated = this._setValueTD(td,sum);
			break;

		default:
			alert(row_game);
	}
	
	if(!fieldUpdated) {
		return;
	}
	
	this._updateSum(td,column_game, row_game);
	this.decrementCountdown();
	
	if(column_game!="call") {
		this.undo("show", td, column_game, row_game);
	}
	
	this.container.find("ul.dices li").attr("locked",0);
	this.throwCount = 3;
	this.container.find(".display").html(0);
	this.locked = true;
}

Yamb.prototype.undo = function(action, td, column_game, row_game) {
	var _Y = this;
	_Y.table.find('.undo').remove();
	
	var FieldsLeft = parseInt(this.container.find(".yamb-countdown").html());
	
	if(action == "show" && FieldsLeft>0) {
		var undo = $('<a href="javascript:void(0)" class="undo">undo</a>');
		_Y.table.find("tr:first td:last").append(undo);
		undo.show();
		undo.click(function(){
			_Y._setValueTD(td,"",true);
			td.removeAttr("value");
			_Y._updateSum(td,column_game, row_game);
			_Y.throwCount = 0;
			_Y.container.find(".display").html(3-_Y.throwCount);
			_Y.decrementCountdown(1);
			_Y.locked = false;
			_Y.undo("hide", td, column_game, row_game);
		});
	}
}

Yamb.prototype.gameValueNUM = function(dices, num) {
	if(typeof(dices) == "undefined") {
		dices = this.getDicesValues();
	}
	sum = 0;
	for(x in dices) {
		if(dices[x] == parseInt(num)) {
			sum += dices[x];
		}
	}
	return sum;
}
Yamb.prototype.gameValueSTRAIGHT = function(dices) {
	if(typeof(dices) == "undefined") {
		dices = this.getDicesValues();
	}
	dices.sort();
	val = 0;
	if(dices.length>0) {
		ok=true;
		for(var i=1; i<dices.length; i++) {
			if(!(dices[i]!=dices[i-1] && (dices[i]-dices[i-1])==1)) {
				ok=false;
				break;
			}
		}
		if(ok) {
			val = (this.throwCount+1)*10 + 36;
		}
	}
	return val;
}

Yamb.prototype.decrementCountdown = function(inc) {
	inc = inc ? inc : -1;
	var countdown = this.container.find(".yamb-countdown");
	var throwsLeft = this._getValueTD(countdown)+inc;
	this._setValueTD(countdown,throwsLeft);
	if(throwsLeft==0) {
		this.EndGame();
	}
	
}
Yamb.prototype.calculateSums = function() {
	var Y = this;
	var column_game, previous, value;
	
	// column sums
	Y.container.find("tr.sum td[game]").each(function(){
		column_game = $(this).attr("game");
		if(column_game) {
			previous = $(this).parent().prev();
			total=0;
			while(!previous.hasClass("head") && !previous.hasClass("sum")) {
				//alert(previous.find("td[game="+column_game+"]").attr("value"));break;
				value = parseInt(previous.find("td[game="+column_game+"]").attr("value"));
				total += value>0?value:0;
				previous = previous.prev();
			}
			if(total>0){
				Y._setValueTD($(this), total, true);
			}
		}
	});
	
	// row sums
}
Yamb.prototype.EndGame = function() {
	var Y = this;
	
	// recalculate SUMs
	Y.calculateSums();
	
	// hide stuff
	Y.container.find(".disable-mask").fadeIn(300);
	var resultDiv = $(".result");
	var result = Y._getValueTD($(".yamb-total"));	
	resultDiv.find(".points").html(result);
	resultDiv.slideDown(300);
}
Yamb.prototype._getValueTD = function(td) {
	value = parseInt(td.attr("value"));
	return value>0?value:0;
}
Yamb.prototype._setValueTD = function(td, value, silent) {
	silent = silent ? true : false;
	
	if(this.called && !td.attr("called")) {
		return;
	}
	if(!silent) {
		value = parseInt(value); value=value>0?value:0;
	}
	if(value==0 && td.hasClass("field") && !silent) {
		if(!confirm("Do you want to scratch this field?")) {
			return false;
		}
	}
	td.attr("value", value);
	td.html(value);
	return true;
}

Yamb.prototype._updateSum = function(td, column_game, row_game) {
	tr = this.getSumTR(td);
	
	var sum_td = tr.find("td[game="+column_game+"]");
	
	if(row_game.match(/^max$|^min$/)) {
		var first = this.table.find("tr[game=1] td[game="+column_game+"]");
		var max, min;
		if(row_game == "max") {
			max = td;
			min = this.table.find("tr[game=min] td[game="+column_game+"]");
		}else{
			min = td;
			max = this.table.find("tr[game=max] td[game="+column_game+"]");
		}
		
		first_val = first.attr("value");
		min_val = min.attr("value");
		max_val = max.attr("value");
		if(typeof(first_val)!="undefined" && typeof(min_val)!="undefined" && typeof(max_val)!="undefined") {
			tmp = (max_val-min_val)*first_val; tmp=tmp>0?tmp:0;
			this._setValueTD(sum_td,tmp);
		}
	}else{	
		var sum = parseInt(sum_td.attr("value")); sum=sum>0?sum:0;
		sum = sum + parseInt(td.attr("value"));
		if(row_game.match(/^[123456]$/) && sum>=60 && !sum_td.attr("bonus")) {
			sum += 30;
			sum_td.attr("bonus",1);
		}
		this._setValueTD(sum_td,sum);
		
		if(row_game==1) {
			first = td;
			max = this.table.find("tr[game=max] td[game="+column_game+"]");
			min = this.table.find("tr[game=min] td[game="+column_game+"]");
			sum_td = this.getSumTR(max).find("td[game="+column_game+"]");
			
			first_val=first.attr("value");
			max_val=max.attr("value");
			min_val=min.attr("value");
			if(typeof(first_val)!="undefined" && typeof(max_val)!="undefined" && typeof(min_val)!="undefined") {
				
				first_val=parseInt(first_val);
				max_val=parseInt(max_val);
				min_val=parseInt(min_val);
				
				first_val=first_val>0?first_val:0;
				max_val=max_val>0?max_val:0;
				min_val=min_val>0?min_val:0;
				
				tmp = (max_val-min_val)*first_val; tmp=tmp>0?tmp:0;
				this._setValueTD(sum_td,tmp);
				this._updateSumTotal(sum_td.parent());
			}
		}
	}
	
	this._updateSumTotal(tr);
}

Yamb.prototype._updateSumTotal = function(tr) {
	// row total
	var sum_tr = 0;
	var has1AtLeast = false;
	var val;
	tr.find("td").each(function(index){
		if(!$(this).hasClass("total,label")) {
			val = $(this).attr("value");
			if(typeof(val)) {
				has1AtLeast = true;
			}
			tmp = parseInt(val);
			sum_tr += tmp>0?tmp:0;
		}
	});
	if(has1AtLeast) {
		this._setValueTD(tr.find("td.total"),sum_tr);
	}else{
		return;
	}
	
	// total
	total = 0;
	this.table.find("td.total").each(function(){
		if(!$(this).hasClass("yamb-total")) {
			tmp = parseInt($(this).attr("value"));
			tmp = tmp>0 ? tmp : 0;
			total += tmp;
		}
	});
	this._setValueTD(this.table.find("td.yamb-total"),total);
}

Yamb.prototype.getSumTR = function(td) {
	var tr = td.parent();
	while(!tr.hasClass("sum")) {
		tr = tr.next();
		if(!tr.length) {
			tr = null;
			break;
		}
	}
	return tr;
}

Yamb.prototype.getDicesValues = function() {
	var ret = [];
	this.container.find("ul.dices li[locked=1]").each(function(){
		ret.push($(this).attr("value"));
	});
	return ret;
}